/*
	尝试过typeof判断后添加，
	后来栽在 @@Iterator 对象上，
	遂放弃浏览器判断，改覆写原生fun，
	如果撤掉，有不少部分的写法和ES6有很大的不同的
	坑到谁，算谁倒霉，反正本来就是为了IE8兼容用的
 */

if (typeof Array.prototype.close != "function") {
	Array.prototype.close = function(){
		var result = new Array();
		for(var i=0;i<this.length;i++){
			result[i]=this[i]
		}
		return result;
	}
}//深拷贝，也许这个DIY的会有用
if (!Array.of) {
  Array.of = function() {
    return Array.prototype.slice.call(arguments);
  };
}//来自MDN的代码，ES2015，反正IE不支持就是了

if(!Array.prototype.isArray) {
  Array.prototype.isArray = function(obj){
  	return Object.prototype.toString.call(obj) == "[object Array]";
	}
}
// arr.isArray(arr)//true //实际调用方法，极大的讽刺

// if(!Array.prototype.unshift) {
//   Array.prototype.unshift = function(value){
//   	for(var i=this.length;i>=0;i--){
//   		this[i]=this[i-1];
//   	}
//   	this[0]=value;
//   }
// }备用
// 菜鸟提到：unshift()方法不能用于IE8之前的版本，插入的值将被返回成 undefined 。
// 无实测记录；
// 大概IE8可行；

if (typeof Array.prototype.indexOf != "function") {
	Array.prototype.indexOf = function (searchElement, fromIndex) {
		var index = -1;
		fromIndex = fromIndex >>> 0;//位运算，非法参数转0处理，小数取整处理
		var len = this.length;
		for (var k=0;k<len;k++) {
			if (k >= fromIndex && this[k] === searchElement) {
				index = k;
				break;
			}
		}
		return index;
	};
}//ie7
if (typeof Array.prototype.lastIndexOf != "function") {
	Array.prototype.lastIndexOf = function (searchElement, fromIndex) {
		var index = -1;
		var len = this.length;
		fromIndex = fromIndex * 1 || len - 1;//无法使用的值等同于NaN
		for (var k=len-1;k>-1;k-=1) {
			if (k <= fromIndex && this[k] === searchElement) {
				index = k;
				break;
			}
		}
		return index;
	};
}//ie7

if (typeof Array.prototype.every != "function") {
	Array.prototype.every = function (fn, context) {
		var passed = true;
		if (typeof fn === "function") {
			for (var k = 0, length = this.length; k < length; k++) {
				if (passed === false) { break };
				passed = !!fn.call(context, this[k], k, this);
			}
		}else{
			throw new TypeError(fn.toString()+" is not a function")
		}
		return passed;
	};
}//ie8
if (typeof Array.prototype.some != "function") {
	Array.prototype.some = function (fn, context) {
		var passed = false;
		if (typeof fn === "function") {
			for (var k = 0, length = this.length; k < length; k++) {
				if (passed === true) { break };
				passed = !!fn.call(context, this[k], k, this);
			}
		}else{
			throw new TypeError(fn.toString()+" is not a function")
		}
		return passed;
	};
}//ie8
if (typeof Array.prototype.fill != "function") {
	Array.prototype.fill = function(value,start,end){		
		var strat = start >>> 0;//位运算，非法参数转0处理，小数取整处理; //可选。开始填充位置。
		var end = end * 1 || this.length; //可选。停止填充位置 (默认为 array.length)
		if ( start>end ){ throw "start>end"; }
		for(var i=start;i<end;i++){
  		this[i]=value;
  	}
  }
}//ES6 ie12
if (typeof Array.prototype.copyWithin != "function") {
	Array.prototype.copyWithin = function(target,start,end){
    var len = this.length >>> 0;
		var relativeTarget = target >> 0;
    var to = relativeTarget < 0 ? Math.max(len + relativeTarget, 0) : Math.min(relativeTarget, len);
    var relativeStart = start >> 0;
    var from = relativeStart < 0 ? Math.max(len + relativeStart, 0) : Math.min(relativeStart, len);
    var end = end;
    var relativeEnd = end === undefined ? len : end >> 0;
    var final = relativeEnd < 0 ? Math.max(len + relativeEnd, 0) : Math.min(relativeEnd, len);
    var count = Math.min(final - from, len - to);
    var direction = 1;
    if (from < to && to < (from + count)) {
      direction = -1;
      from += count - 1;
      to += count - 1;
    }
    while (count > 0) {
      if (from in this) {
        this[to] = this[from];
      } else {
        delete this[to];
      }
      from += direction;
      to += direction;
      count--;
    }
    return this;
  }
}//ES6 ie12 //这个理解费劲

if (typeof Array.prototype.find != "function") {
	Array.prototype.find = function (fn, scope) {
		var i;
		var len = this.length;
		var result = undefined;
		if (typeof fn === "function") {
			for (i=0;i<len;i++) {
				if(!!fn.call(scope, this[i], i, this)){
					result = this[i];break;
				}
			}
		}else{
			throw new TypeError(fn.toString()+" is not a function");
		}
		return result;
  };
}//ES6 ie12
if (typeof Array.prototype.findIndex != "function") {
	Array.prototype.findIndex = function (fn, scope) {
		var i;
		var len = this.length;
		var result = -1;
		if (typeof fn === "function") {
			for (i=0;i<len;i++) {
				if(!!fn.call(scope, this[i], i, this)){
					result = i;
					break;
				}
			}
		}else{
			throw new TypeError( fn.toString()+" is not a function" );
		}
		return result;
  };
}//ES6 ie12


if (typeof Array.prototype.filter != "function") {
	Array.prototype.filter = function (fn, context) {
		var arr = new Array();
		var len = this.length;
		if (typeof fn === "function") {
			for (var k=0;k<len;k++) {
				fn.call(context, this[k], k, this) && arr.push(this[k]);
			}
		}else{
			throw new TypeError(fn.toString()+" is not a function");
		}
		return arr;
	};
}//ES6 ie9

if (typeof Array.prototype.map != "function") {
	Array.prototype.map = function (fn, context) {
		var arr = new Array();
		var len = this.length;
		if (typeof fn === "function") {
			for (var k = 0;k<len;k++) {
				arr.push(fn.call(context, this[k], k, this));
			}
		}else{
			throw new TypeError(fn.toString()+" is not a function");
		}
		return arr;
	};
}//ES6 ie9

if (typeof Array.prototype.forEach != "function") {
  Array.prototype.forEach = function (fn, scope) {
		var i;
		var len = this.length;
		if (typeof fn === "function") {
			for (i=0;i<len;i++) {
				if (i in this) {
					fn.call(scope, this[i], i, this);
				}
			}
		}else{
			throw new TypeError(fn.toString()+" is not a function");
		}
		return undefined;
  };
}//ES6 ie9

if (typeof Array.prototype.includes != "function") {
	Array.prototype.includes = function (searchElement, fromIndex) {
		var result = false;
		fromIndex = fromIndex >>> 0;//位运算，非法参数转0处理，小数取整处理;
		var len = this.length;
		for (var k=0;k<len;k++) {
			if (k >= fromIndex && this[k] === searchElement) {
				result = true;
				break;
			}
		}
		return result;
	};
}//ES6 <ie14

if (typeof Array.prototype.reduce != "function") {
	Array.prototype.reduce = function (callback, initialValue ) {
		var previous = initialValue;
		var len = this.length;
		var strat = 0;
		if (typeof initialValue === "undefined") {
			previous = this[0];
			strat = 1;
		}
		if (typeof callback === "function") {
			for (var k=strat;k<len;k++) {
				this.hasOwnProperty(k) && (previous = callback(previous, this[k], k, this));
			}
		}else{
			throw new TypeError(callback.toString()+" is not a function");
		}
		return previous;
	};
}//ie9
if (typeof Array.prototype.reduceRight != "function") {
	Array.prototype.reduceRight = function (callback, initialValue ) {
		var previous = initialValue;
		var len = this.length;
		var strat = len;
		if (typeof initialValue === "undefined") {
			previous = this[len-1];
			strat = len-1;
		}
		if (typeof callback === "function") {
			for (var k=strat;k>-1;k--) {
				this.hasOwnProperty(k) && (previous = callback(previous, this[k], k, this));
			}
		}else{
			throw new TypeError(callback.toString()+" is not a function");
		}
		return previous;
	};
}//ie9

// array.from()
// array.entries()
// array.keys()
// array.values()

//不少部分和ES6的Set是不同的
function Set(){
	this.items = new Object();
	this.size = 0;
	return this;
}
Set.prototype = {
	has:function(element){
		return Object.prototype.hasOwnProperty.call(this.items,element);
	}
	,add:function(element){
		if( !this.has(element) ){
			this.items[element] = element;
			this.size++;
			return true;
		}
		return false;
	}
	,del:function(element){
		if( this.has(element)){
			delete this.items[element];
			this.size--;
			return true;
		}
		return false;
	}//delete 关键字不能作为IE8下的方法名
	,clear:function(){
		this.items = {};
		this.size = 0;
		return this;
	}
	,getSize:function(){
		return this.size;
		// ES2015
		// return Object.keys(this.items).length;
	}
	,keys:function(){
		var keys = [];
		for(var key in this.items){
			if(this.items.hasOwnProperty(key)){
				keys.push(key);
			}
		}
		return keys;
	}
	,values:function(){
		var values = [];
		for(var key in this.items){
			if(this.items.hasOwnProperty(key)){
				values.push(key);
			}
		}
		return values;
		// ES2015
		// return Object.values(this.items)
	}
	,union:function (otherSet) {
		var unionSet = new Set();//两个集合的并集
		var values = this.values();//第一个集合
		for(var i=0;i<values.length;i++){
			unionSet.add(values[i]);
		}//迭代全部并添加到并集中；
		values = otherSet.values();//第二个集合
		for(var i=0;i<values.length;i++){
			unionSet.add(values[i]);
		}//迭代全部并添加到并集中(has()判断过滤)；
		return unionSet;
	}//并集
	,intersection:function(otherSet){
		var intersectionSet = new Set();
		var biggerSet = this;
		var smallerSet = otherSet;
		if(biggerSet.getSize()<smallerSet.getSize()){
			var biggerSet = otherSet;
			var smallerSet = this;
		}
		var bigValues = biggerSet.values();
		var smallerValues = smallerSet.values()
		//优化，迭代小size，检测大size
		for(var i=0;i<smallerValues.length;i++){
			if( biggerSet.has(smallerValues[i]) ){
				intersectionSet.add(smallerValues[i]);
			}
		}
		return intersectionSet;
	}//交集
	,difference:function(otherSet){
		var differenceSet = new Set();
		var values = this.values();
		for(var i=0;i<values.length;i++){
			if( !otherSet.has(values[i]) ){
				differenceSet.push(values[i]);
			}
		}
		return differenceSet;
	}//差集
	,isSubsetOf:function(otherSet){
		if( this.getSize() > otherSet.getSize() ){
			return false;
		}
		var isSubset = true;
		var values = this.values()
		for(var i=0;i<values.length;i++){
			if(isSubset === false){ break }
			isSubset = otherSet.has(values[i]);
		}
		return isSubset;
	}//子集，返回布尔
};

if (typeof Object.prototype.length != "function") {
	Object.prototype.length = function() {
	  var count = 0;
	  for(var i in this){
	    count ++;
	  }
		return count;
	};
}
if (typeof Object.prototype.map != "function") {
	Array.prototype.map = function (fn, context) {
		var arr = new Array();
		var len = this.length;
		if (typeof fn === "function") {
			for (var k = 0;k<len;k++) {
				arr.push(fn.call(context, this[k], k, this));
			}
		}else{
			throw new TypeError(fn.toString()+" is not a function");
		}
		return arr;
	};
}//ES6 ie9

